package me.shurufa.utils;

import android.util.Log;
import java.util.Hashtable;

/**
 * use for Log by user
 * if debug model ,recommend to use :LogUtils.xxxUser.e(str)
 *
 * @FileName: me.shurufa.utils.LogUtils.java
 * @author: kHRYSTAL
 * @email: 723526676@qq.com
 * @date: 2016-01-12 20:02
 */
public class LogUtils {
  private final static boolean logFlag = Global.DEBUG;

  public final static String tag = "ShuRuFa";
  private final static int logLevel = Log.VERBOSE;
  private static Hashtable<String, LogUtils> sLoggerTable = new Hashtable<String, LogUtils>();
  private String mClassName;

  private static LogUtils yLog;
  private static LogUtils kLog;

  private static final String YGXDXX = "@ygxdxx@ ";
  private static final String KHRTSTAL = "@khrystal@ ";

  private LogUtils(String name) {
    mClassName = name;
  }

  /**
   *
   * @param className
   * @return
   */
  @SuppressWarnings("unused")
  private static LogUtils getLogger(String className) {
    LogUtils classLogger = (LogUtils) sLoggerTable.get(className);
    if (classLogger == null) {
      classLogger = new LogUtils(className);
      sLoggerTable.put(className, classLogger);
    }
    return classLogger;
  }

  /**
   * Purpose:Mark user one
   *
   * @return
   */
  public static LogUtils kLog() {
    if (kLog == null) {
      kLog = new LogUtils(KHRTSTAL);
    }
    return kLog;
  }

  /**
   * Purpose:Mark user two
   *
   * @return
   */
  public static LogUtils yLog() {
    if (yLog == null) {
      yLog = new LogUtils(YGXDXX);
    }
    return yLog;
  }

  /**
   * Get The Current Function Name
   *
   * @return
   */
  private String getFunctionName() {
    StackTraceElement[] sts = Thread.currentThread().getStackTrace();
    if (sts == null) {
      return null;
    }
    for (StackTraceElement st : sts) {
      if (st.isNativeMethod()) {
        continue;
      }
      if (st.getClassName().equals(Thread.class.getName())) {
        continue;
      }
      if (st.getClassName().equals(this.getClass().getName())) {
        continue;
      }
      return mClassName + "[ " + Thread.currentThread().getName() + ": "
          + st.getFileName() + ":" + st.getLineNumber() + " "
          + st.getMethodName() + " ]";
    }
    return null;
  }

  /**
   * The Log Level:i
   *
   * @param str
   */
  public void i(Object str) {
    if (logFlag) {
      if (logLevel <= Log.INFO) {
        String name = getFunctionName();
        if (name != null) {
          Log.i(tag, name + " - " + str);
        } else {
          Log.i(tag, str.toString());
        }
      }
    }

  }

  /**
   * The Log Level:d
   *
   * @param str
   */
  public void d(Object str) {
    if (logFlag) {
      if (logLevel <= Log.DEBUG) {
        String name = getFunctionName();
        if (name != null) {
          Log.d(tag, name + " - " + str);
        } else {
          Log.d(tag, str.toString());
        }
      }
    }
  }

  /**
   * The Log Level:V
   *
   * @param str
   */
  public void v(Object str) {
    if (logFlag) {
      if (logLevel <= Log.VERBOSE) {
        String name = getFunctionName();
        if (name != null) {
          Log.v(tag, name + " - " + str);
        } else {
          Log.v(tag, str.toString());
        }
      }
    }
  }

  /**
   * The Log Level:w
   *
   * @param str
   */
  public void w(Object str) {
    if (logFlag) {
      if (logLevel <= Log.WARN) {
        String name = getFunctionName();
        if (name != null) {
          Log.w(tag, name + " - " + str);
        } else {
          Log.w(tag, str.toString());
        }
      }
    }
  }

  /**
   * The Log Level:e
   *
   * @param str
   */
  public void e(Object str) {
    if (logFlag) {
      if (logLevel <= Log.ERROR) {
        String name = getFunctionName();
        if (name != null) {
          Log.e(tag, name + " - " + str);
        } else {
          Log.e(tag, str.toString());
        }
      }
    }
  }

  /**
   * The Log Level:e
   *
   * @param ex
   */
  public void e(Exception ex) {
    if (logFlag) {
      if (logLevel <= Log.ERROR) {
        Log.e(tag, "error", ex);
      }
    }
  }

  /**
   * The Log Level:e
   *
   * @param log
   * @param tr
   */
  public void e(String log, Throwable tr) {
    if (logFlag) {
      String line = getFunctionName();
      Log.e(tag, "{Thread:" + Thread.currentThread().getName() + "}"
          + "[" + mClassName + line + ":] " + log + "\n", tr);
    }
  }

  // static method not by user
  public static final boolean DEBUGGABLE = true;

  private static final int MAX_ENABLED_LOG_LEVEL = DEBUGGABLE
      ? android.util.Log.VERBOSE
      : android.util.Log.INFO;

  public static boolean isLoggable(int level) {
    return MAX_ENABLED_LOG_LEVEL <= level;
  }


  public static void v(String tag, String msg) {
    if (logFlag) {
      android.util.Log.v(tag, msg);
    }
  }


  public static void d(String tag, String msg) {
    if (logFlag) {
      android.util.Log.d(tag, msg);
    }
  }

  public static void i(String tag, String msg) {
    if (logFlag) {
      android.util.Log.i(tag, msg);
    }
  }

  public static void w(String tag, String msg) {
    if (logFlag) {
      android.util.Log.w(tag, msg);
    }
  }

  public static void e(String tag, String msg) {
    if (logFlag) {
      android.util.Log.e(tag, msg);
    }
  }

  public static void wtf(String tag, String msg) {
    if (isLoggable(android.util.Log.ASSERT)) {
      android.util.Log.wtf(tag, msg);
    }
  }
}
